#!/bin/sh -e
# perp: persistent process supervision
# perp-setup: one-time, post-install configurator for perp
# wcm, 2009.12.23 - 2012.01.04
# ===
## basename:
_PROG=${0##*/}
_PID=$$

_BASE_DEFAULT=/etc/perp
_CTL_DEFAULT=/var/run/perp

_BASE=${PERP_BASE:-${_BASE_DEFAULT}}
_CTL=${PERP_CTL:-${_CTL_DEFAULT}}

_INITTAB=/etc/inittab
_RCLOCAL=/etc/rc.local

_mesg() {
  echo "${_PROG}(${_PID}): $1" >/dev/stderr  
}

_fail() {
  _mesg "failure: $1"
  exit 1
}

_done() {
  _mesg "perp configured."
  exit 0
}

## command-line override for _BASE, _CTL:
if test $# -gt 0 ; then
  _BASE=${1:-${_BASE}}
fi
if test $# -gt 1 ; then
  _CTL=${2:-${_CTL}}
fi

if test 'X' != ${DESTDIR}'X' ; then
  _mesg "configuring perp in DESTDIR ${DESTDIR} for ${_BASE} ..."
else
  _mesg "configuring perp for ${DESTDIR}${_BASE} ..."
fi

if ! test -d ${DESTDIR}${_BASE} ; then
  mkdir -p ${DESTDIR}${_BASE} || _fail "unable to create base directory"
fi

if ! test -d ${DESTDIR}${_BASE}/.boot ; then
  mkdir -p ${DESTDIR}${_BASE}/.boot || _fail "unable to create .boot directory"
fi

if ! test -e ${DESTDIR}${_BASE}/.control -o -L ${DESTDIR}${_BASE}/.control ; then
  ## create symlink to control directory (possibly dangling):
  ln -s ${_CTL} ${DESTDIR}${_BASE}/.control || \
    _fail "unable to create symlink for .control directory"
fi

_mesg "configuring perpboot directory in ${DESTDIR}${_BASE}/.boot ..."

## clean any pre-existing *.new files:
for f in rc.log rc.perp rlimit.conf ; do
  rm -f ${DESTDIR}${_BASE}/.boot/${f}.new
done

## rlimit.conf:
cat - > ${DESTDIR}${_BASE}/.boot/rlimit.conf.new << "%%"
# rlimit.conf
# runlimit setup for perpd
# ===
## set RLIMIT_NOFILE and RLIMIT_NPROC to hard limit:
RLIMIT_NOFILE=^
RLIMIT_NPROC=^
### EOF
%%

## rc.perp:
cat - > ${DESTDIR}${_BASE}/.boot/rc.perp.new << "%%"
#!/bin/sh -e
# rc.perp: perpd startup script for perpboot
# ===

### --- configure ---
PERPD_OPTS="-a6"

### --- script ---

## exec perpd:
##   * options as configured above
##   * runchoom(8) abate linux oom-killer
##   * runlimit(8) configured in ./rlimit.conf
##   * PERP_BASE defined in environment by perpboot(8)
exec \
  runchoom \
  runlimit -F ./rlimit.conf \
  perpd ${PERPD_OPTS} ${PERP_BASE}

### EOF
%%

## rc.log:
cat - > ${DESTDIR}${_BASE}/.boot/rc.log.new << "%%"
#!/bin/sh
# rc.log: perpd logger script for perpboot
# ===

### --- configure ---

## required:
LOGDIR=/var/log/perpd
LOGOPTS="-k 8 -s 100000 -t -z"
## suggested:
LOGUSER=tinylog

### --- script ---

## initialize user:
if id ${LOGUSER} >/dev/null 2>/dev/null ; then
  my_uid=$(id -u ${LOGUSER})
  my_gid=$(id -g ${LOGUSER})
else
  LOGUSER=$(id -un)
  my_uid=$(id -u ${LOGUSER})
  my_gid=$(id -g ${LOGUSER})
fi

## initialize logdir:
if ! test -d ${LOGDIR} ; then
  mkdir -p ${LOGDIR}
fi
chown -R ${my_uid}:${my_gid} ${LOGDIR}
chmod 0755 ${LOGDIR}

## exec tinylog with privilege drop:
exec \
  runuid ${LOGUSER} \
      tinylog ${LOGOPTS} ${LOGDIR}

### EOF
%%

for f in rlimit.conf ; do
  if ! test -f ${DESTDIR}${_BASE}/.boot/${f} ; then
    mv ${DESTDIR}${_BASE}/.boot/${f}.new ${DESTDIR}${_BASE}/.boot/${f}
    chmod 0644 ${DESTDIR}${_BASE}/.boot/${f}
  fi
done

for f in rc.perp rc.log ; do
  if ! test -f ${DESTDIR}${_BASE}/.boot/${f} ; then
    mv ${DESTDIR}${_BASE}/.boot/${f}.new ${DESTDIR}${_BASE}/.boot/${f}
    chmod 0755 ${DESTDIR}${_BASE}/.boot/${f}
  fi
done

_mesg "perpboot directory configured"


## skip init configuration?
if test 'X' != ${DESTDIR}'X' ; then
  _mesg "DESTDIR defined, skipping startup configuration"
  _done
fi
if test 'X' != ${NO_INIT}'X' ; then
  _mesg "NO_INIT defined, skipping startup configuration"
  _done
fi


## /etc/inittab installation (sysv):
if test -f ${_INITTAB} ; then
  _mesg "configuring perpboot entry for ${_INITTAB} ..."
  if fgrep perpboot ${_INITTAB} >/dev/null 2>/dev/null ; then
      _mesg "perpboot entry already found in ${_INITTAB}"
      _done
  else
      rm -f ${_INITTAB}.new 
      cat ${_INITTAB} - > ${_INITTAB}.new << %%

## perp:
PB:12345:respawn:@@SBIN@@/perpboot -x ${_BASE}

### EOF
%%
      mv ${_INITTAB}.new ${_INITTAB}
      _mesg "perpboot entry added to ${_INITTAB}"
      _mesg "*** please run \"kill -HUP 1\" to activate ***"
      # kill -HUP 1
      _done
  fi
fi

## /etc/rc.local installation (bsd):
if test -f ${_RCLOCAL} ; then
  _mesg "configuring perpboot entry for ${_RCLOCAL} ..."
  if fgrep perpboot ${_RCLOCAL} >/dev/null 2>/dev/null ; then
      _mesg "perpboot entry already found in ${_RCLOCAL}"
      _done
  else
      rm -f ${_RCLOCAL}.new 
      cat ${_RCLOCAL} - > ${_RCLOCAL}.new << %%

## perp:
if [ -x @@SBIN@@/perpboot ]; then
    echo -n ' perpd'
        ## to modify path within perp runscripts, edit/uncomment:
        #PATH=/sbin:/bin:/usr/sbin:/usr/bin \\
        @@SBIN@@/perpboot -d ${_BASE}
fi

### EOF
%%
      mv ${_RCLOCAL}.new ${_RCLOCAL}
      _mesg "perpboot entry added to ${_RCLOCAL}"
      _mesg "*** please restart system to activate ***"
      _done
  fi
fi


_mesg "uh oh, neither ${_INITTAB} nor ${_RCLOCAL} were found on your system!"
_mesg "this system will require manual startup configuration for perpd(8)/perpboot(8)"
exit 1

### EOF
